// 功能组件混入对象
import PnDesigner from "@/utils/PnDesigner";

const FuncCompMixin = {
  props: {
    location: {
      type: String,
      default: ''
    }
  },
  created () {
    // 组件初始化前通过根组件（也就是AbsoluteLayout或ReactiveLayout）中声明的provide setChildrenRef()对当前组件进行实例挂载
    if(this.$store.state.release.pageMetadata) {
      this.setChildrenRef(this.component.id, this)
    }
  },
  mounted() {
    this.componentId = this.component.id;

    this.interactionStreamMonitor()

    this.$EventBus.$on('pn_dynamic_loading_exception', () => {
      this.outLoading()
    })
  },
  destroyed () {
    this.$EventBus.$off('pn_theme_change_' + this.componentId);
    this.$EventBus.$off('pn_interaction_stream');
    this.$EventBus.$off('pn_interaction_stream_manual');
    this.$EventBus.$off('pn_dynamic_loading_exception');
    this.$EventBus.$off('pn_init_datasource_' + this.componentId);

    // 清除定时器
    if(this.timer) {
      clearInterval(this.timer);
    }

    if (this.wsObj.readyState != null) {
      this.wsObj.close();
    }
  },
  data () {
    return {
      componentId: null,
      timer: null,
      runCustomGlobalJsCodeFlag: -1, // 标识是否可也运行全局脚本
      wsObj: {
        readyState: null
      },  // WS对象
      controlledModeExecuted: false, // 是否已执行过受控模式，当组件开启受控模式时，发布状态下首次加载组件将会阻断initDatasource函数的运行，并将此值设置为true
    }
  },
  inject: {
    inLoading: {default: 'inLoading'},
    outLoading: {default: 'outLoading'},
    setChildrenRef: {
      default: () => {}
    },
    getParentRef: {
      from: 'getThisRef',
      default: () => {}
    },
    getParentChildrenRef: {
      from: 'getChildrenRef',
      default: () => {}
    }
  },
  methods: {

    /**
     * 初始化数据源（只有设置数据源配置的组件才需要使用此函数初始化数据）
     * @param _staticCallback 静态数据源回调
     * @param _dynamicCallback 动态数据源回调
     */
    initDatasource (_staticCallback, _dynamicCallback) {
      if (this.$store.state.release.pageMetadata && this.component.compConfigData.ds_controlledMode && !this.controlledModeExecuted) {
        this.controlledModeExecuted = true
        return
      }
      if(this.component.compConfigData.ds_type == 'api' && this.component.compConfigData.ds_apiPath) {
        this.inLoading()
        if (this.component.compConfigData.ds_useHttpServerProxy) {
          this.$PnApi.HttpProxyApi.httpQuery(
            this.component.compConfigData.ds_apiMethod,
            this.$PnUtil.buildApiPath(this.component.compConfigData.ds_apiPath, this.component.compConfigData.ds_linkageUrlParams),
            this.component.compConfigData.ds_apiHeaders,
            this.component.compConfigData.ds_apiPostData).then(result => {
            this.outLoading()
            this.component.compConfigData.ds_resultObj = this.$PnDesigner.dsResultObjClipping(this.component.compConfigData, result.data);
            _dynamicCallback(result);
            this.runDynamicDatasourceSuccessCallbackCode(result)
          }).catch(error => {
            this.$EventBus.$emit('pn_dynamic_loading_exception')
          })
        }else {
          this.$PnApi.httpQuery(
            this.component.compConfigData.ds_apiMethod,
            this.$PnUtil.buildApiPath(this.component.compConfigData.ds_apiPath, this.component.compConfigData.ds_linkageUrlParams),
            this.component.compConfigData.ds_apiHeaders,
            this.component.compConfigData.ds_apiPostData).then(result => {
            this.outLoading()
            this.component.compConfigData.ds_resultObj = this.$PnDesigner.dsResultObjClipping(this.component.compConfigData, result.data);
            _dynamicCallback(result);
            this.runDynamicDatasourceSuccessCallbackCode(result)
          }).catch(error => {
            this.$EventBus.$emit('pn_dynamic_loading_exception')
          })
        }
      }else if (this.component.compConfigData.ds_type == 'websocket' && this.component.compConfigData.ds_wsPath) {
        if(this.$store.state.release.pageMetadata) {
          this.wsObj = this.$WebSocketUtil.initWebSocket(this.component.compConfigData.ds_wsPath, this.layoutItem);
          if (this.wsObj.readyState == 0) {
            this.wsObj.onmessage = (result) => {
              let newResult = {data: result.data}
              if (Object.prototype.toString.call(newResult.data) === '[object String]') {
                newResult.data = JSON.parse(newResult.data)
              }
              this.component.compConfigData.ds_resultObj = newResult.data;
              _dynamicCallback(newResult);
            }
          }
        }else {
          let compConfigData = this.$PnUtil.getCompConfigData(this.$options._componentTag);
          let newResult = {data: compConfigData.ds_resultObj}
          this.component.compConfigData.ds_resultObj = newResult.data;
          _dynamicCallback(newResult);
        }
      }else if (this.component.compConfigData.ds_type == 'database' && this.component.compConfigData.ds_database) {
        this.inLoading()
        this.$PnApi.DatabaseApi.invokeSql(this.component.compConfigData.ds_database, this.component.compConfigData.ds_sql).then(result => {
          if (result.data.success) {
            this.outLoading()
            let newResult = {
              data: result.data.payload
            };
            this.component.compConfigData.ds_resultObj = this.$PnDesigner.dsResultObjClipping(this.component.compConfigData, newResult.data);
            _dynamicCallback(newResult);
          }else {
            this.$EventBus.$emit('pn_dynamic_loading_exception')
            this.$Message.error({
              content: '布局块【' + (this.layoutItem.aliasName ? this.layoutItem.aliasName : this.layoutItem.id) + '】绑定的组件【' +this.component.name+ '】数据源请求出错',
              duration: 5
            });
          }
          this.runDynamicDatasourceSuccessCallbackCode(result.data)
        })
      }else if (this.component.compConfigData.ds_type == 'shareDatasource' && this.component.compConfigData.ds_shareDatasourceKey) {
        this.inLoading()
        this.$EventBus.$on('pn_shareDatasourceResultSet_' + this.component.compConfigData.ds_shareDatasourceKey, (resultSet) => {
          let newResult = {
            data: resultSet
          };
          this.outLoading()
          this.component.compConfigData.ds_resultObj = newResult.data;
          _dynamicCallback(newResult);
        })
      }else if (this.component.compConfigData.ds_type == 'csv' && this.component.compConfigData.ds_csvDatasourceName) {
        this.inLoading()
        this.$PnApi.CsvDatasourceApi.getCsvDatasourceByName(this.component.compConfigData.ds_csvDatasourceName).then(result=>{
          if (result.data.success) {
            this.outLoading()
            let newResult = {
              data: JSON.parse(result.data.payload.json_data)
            };
            this.component.compConfigData.ds_resultObj = newResult.data;
            _dynamicCallback(newResult);
          }else {
            this.$EventBus.$emit('pn_dynamic_loading_exception')
            this.$Message.error({
              content: '布局块【' + (this.layoutItem.aliasName ? this.layoutItem.aliasName : this.layoutItem.id) + '】绑定的组件【' +this.component.name+ '】数据源请求出错',
              duration: 5
            });
          }
          this.runDynamicDatasourceSuccessCallbackCode(result.data)
        })
      }else {
        _staticCallback();
      }

      this.$EventBus.$emit('pn_init_datasource_' + this.componentId)
    },

    /**
     * 内置交互流监听器
     */
    interactionStreamMonitor () {
      // 判断当前组件是否开启了内置交互接收者权限
      if (this.component.compConfigData.interaction_receive) {
        // 使用正则表达式判断当前组件中，是否监听了内置交互变量
        let pattern = (bindingVariateName) => {
          return new RegExp("(?<={{)"+bindingVariateName+".*(?=}})", "g")
        }
        // 监听内置交互流事件
        this.$EventBus.$on('pn_interaction_stream', (fieldsMap) => {
          let compConfigDataStr = JSON.stringify(this.component.compConfigData)
          let flag = false;
          for (let i=0; i<fieldsMap.length; i++) {
            if (pattern(fieldsMap[i].bindingVariateName).test(compConfigDataStr)) {
              flag = true;
              break
            }
          }
          if (flag) {
            this.init()
          }
        })
        // 监听手动发起的内置交互流
        this.$EventBus.$on('pn_interaction_stream_manual', (sender) => {
          let compConfigDataStr = JSON.stringify(this.component.compConfigData)
          let flag = false;
          if (sender.type === 'single') {
            if (pattern(sender.data.bindingVariateName).test(compConfigDataStr)) {
              flag = true;
            }
          }else if (sender.type === 'multiple') {
            for (let i=0; i<sender.data.length; i++) {
              // 如果是手动发起一组内置交互流，那么只要当前组件中包含一个内置交互流变量的监听，那么就运行运行init函数
              if (pattern(sender.data[i].bindingVariateName).test(compConfigDataStr)) {
                flag = true;
                break
              }
            }
          }

          flag ?  this.init() : undefined
        })
      }
    },

    /**
     * 重绘组件，此函数一般用于运行时动态执行的脚本中使用
     */
    redrawComp () {
      console.log('执行redrawComp重绘普通功能组件，组件ID（' + this.component.id + '）')
      this.init()
    },

    /**
     * 设置定时器（定时器只有在预览和发布模式下可以运行）
     * @param callback
     */
    setTimer (callback) {
      if(this.$store.state.release.pageMetadata) {
        if (this.component.compConfigData.ds_useTimer && this.component.compConfigData.ds_autoRefresh) {
          this.timer = setInterval(() => {
            if (callback && typeof callback === 'function') {
              callback()
            }
          }, this.component.compConfigData.ds_autoRefreshDuration * 1000)
        }
      }
    },

    /**
     * 运行自定义全局脚本代码（初始化运行脚本）
     */
    runCustomGlobalJsCode () {
      if(this.$store.state.release.pageMetadata) {
        if (this.component.compConfigData.customGlobalJsCode) {
          let original_compConfigData = this.component.compConfigData;
          let original_ds_apiPath = this.component.compConfigData.ds_apiPath;
          let original_ds_sql = this.component.compConfigData.ds_sql;
          let original_ds_resultObj = this.component.compConfigData.ds_resultObj;
          if (this.runCustomGlobalJsCodeFlag == -1) {
            eval(this.component.compConfigData.customGlobalJsCode);
            this.runCustomGlobalJsCodeFlag = 1
          }
        }
      }
    },

    /**
     * 运行动态数据源成功回调时执行代码
     */
    runDynamicDatasourceSuccessCallbackCode (response) {
      if (this.$store.state.release.pageMetadata) {
        if (this.component.compConfigData.ds_dynamicDatasourceSuccessCallbackCode) {
          eval(this.component.compConfigData.ds_dynamicDatasourceSuccessCallbackCode);
        }
      }
    },

    /**
     * 运行过滤器并返回过滤后结果集，过滤处理包括字段映射过滤以及自定义过滤器过滤
     * @param data 需要进行过滤处理的结果集数据
     * @returns {*}
     */
    runCustomFilter (data) {
      // return PnDesigner.dsResultObjCustomCodeFilter(this.component.compConfigData, PnDesigner.dsResultObjMappingFilter(this.component.compConfigData, data))
      return PnDesigner.dsResultObjMappingFilter(this.component.compConfigData, PnDesigner.dsResultObjCustomCodeFilter(this.component.compConfigData, data))
    },

    /**
     * 根据组件ID获取vue实例对象，使用此函数，可以在当前组件的动态脚本中获取同页面下的其他组件的vue实例对象
     * @param id 组件ID
     * @returns {*|Vue|Element}
     */
    findCompVmById (id) {
      // try {
      //   if (this.pageMetadata.develop_canvas == 'AbsoluteLayoutCanvas') {
      //     return this.$parent.$parent.$parent.$parent.$children[0].$refs[id][0]
      //   }else if (this.pageMetadata.develop_canvas == 'ReactiveLayoutCanvas') {
      //     return this.$parent.$parent.$parent.$parent.$parent.$parent.$children[0].$refs[id][0]
      //   }
      // }catch (e) {
      //   this.$Message.error({
      //     content: '函数findCompVmById找不到指定ID【'+id+'】的组件实例',
      //     duration: 4
      //   })
      // }
      return this.getParentChildrenRef(id)
    }

  },
  computed: {
    projectInfo () {
      if(this.$store.state.release.pageMetadata) {
        return this.$store.getters['release/getProjectInfo']
      }else {
        return this.$store.getters['designer/getProjectInfo']
      }
    },
    pageMetadata () {
      if(this.$store.state.release.pageMetadata) {
        return this.$store.getters['release/getPageMetadata']
      }else {
        return this.$store.getters['designer/getPageMetadata']
      }
    },
    layoutItem: function () {
      if(this.$store.state.release.pageMetadata) {
        return this.$store.getters['release/getLayoutItemById'](this.location)
      }else {
        return this.$store.getters['designer/getLayoutItemById'](this.location)
      }
    },
    component: function () {
      if(this.$store.state.release.pageMetadata) {
        return this.$store.getters['release/getLayoutItemById'](this.location).component
      }else {
        return this.$store.getters['designer/getLayoutItemById'](this.location).component
      }
    },

    /**
     * 当前页面使用的主题方案的主色调数组
     */
    currentEchartThemeColors () {
      if (this.pageMetadata.theme_json) {
        return this.pageMetadata.theme_json.color
      }else {
        return ['','','','','','','','']
      }
    },

    /**
     * 是否显示布局块遮罩层
     * @returns {boolean}
     */
    shade () {
      if(this.$store.state.release.pageMetadata) {
        return false
      }else {
        return true;
      }
    },

    /**
     * 默认图片
     * @returns {string}
     */
    defaultImg () {
      return 'this.src="'+require('@/assets/image/default-img.png')+'";this.onerror=null'
    }
  }
};

export default FuncCompMixin
